using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Security;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Npoi.Mapper;
using Publicuse.Appication;
using Publicuse.Autofac;
using Publicuse.Cache;
using Publicuse.Entity;
using Publicuse.Interface;
using Publicuse.Interface.Extend;
using Publicuse.Util;
using Publicuse.Util.Jwt;
using Geekeradmin.Authorize;
using Geekeradmin.Common;
using SqlSugar;

namespace Geekeradmin.Controllers
{
  /// <summary>
  /// 权限管理模块
  /// </summary>
  [AllowAnonymous]
  [Route("api/[controller]")]
  [ApiController]
  public class AuthorityController : BaseController
  {
    private DBConnectionOption AuthorityApi = null;

    public ICustomJWTService jWTService;

    private readonly ICaptcha captcha;

    public AuthorityController(
      IAutofaceInstance autoface,
      IMySqlSugarService mySqlSugar,
      IWebHostEnvironment webHost,
      IOptions<DBConnectionOption> options,
      IOptionsMonitor<DBConnectionOption> optionsb,
      ICustomJWTService jWTService,
      ICaptcha captcha,
      IBaseServiceExt baseServiceExt
    )
      : base(autoface, mySqlSugar, webHost, options, baseServiceExt)
    {
      AuthorityApi = optionsb.CurrentValue;
      this.jWTService = jWTService;
      this.captcha = captcha;
    }

    /// <summary>
    /// 登录
    /// </summary>
    /// <param name="userLogin"></param>
    /// <returns></returns>
    [HttpPost("Login")]
    public async Task<JsonResult> Login(UserLogin userLogin)
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult();
        if (
          userLogin == null
          || StringUtil.isHaveNull(
            userLogin.name,
            userLogin.pwd,
            userLogin.verify,
            userLogin.timestamp
          )
        )
        {
          result.msg = ImplementResult.LoginIsNull.GetRemark();
          goto execend;
        }
        var paramJSON = JsonUtil.ToJson(userLogin);
        autoface.DoWork(
          BusinessType.user,
          BusinessActionType.login,
          paramJSON,
          BusinessActionType.login.GetRemark(),
          BusinessLogType.NoWrite,
          (o) =>
          {
            UserLoginResult userLoginResult = null;
            string msg = string.Empty;
            string loginretrytime = string.Empty;
            int errcount = 0;
            int sycs = 0;
            ImplementResult loginResult = this.HttpContext.UserLogin(
              this.AuthorityApi,
              this.mySqlSugar,
              out msg,
              out userLoginResult,
              userLogin.timestamp,
              out loginretrytime,
              out errcount,
              out sycs,
              this.jWTService,
              userLogin.name,
              userLogin.pwd,
              userLogin.verify
            );
            if (ImplementResult.UserSuccess == loginResult)
            {
              result.data = userLoginResult;
              var modulelist = userLoginResult
                .list.Where(o => o.aType == 1 && o.aParentId == 0)
                .OrderBy(o => o.amoduleIndex);
              UserRouteData userRouteData = new UserRouteData();
              List<UsermenuPermissions> routes = new List<UsermenuPermissions>();
              modulelist.ForEach(item =>
              {
                umpMeta meta = new umpMeta()
                {
                  title = item.aName,
                  i18nKey = item.language,
                  icon = item.ahtmlIcon,
                  order = item.amoduleIndex,
                  keepAlive = false
                };
                UsermenuPermissions permissions = new UsermenuPermissions()
                {
                  name = item.aCode,
                  path = item.ahtmlUrl,
                  component = item.component,
                  meta = meta,
                  children = new List<UsermenuPermissions>()
                };
                var menulist = userLoginResult
                  .list.Where(o => o.aParentId == item.Id)
                  .OrderBy(o => o.abIndex)
                  .ToList();
                if (menulist.Count > 0)
                {
                  foreach (var itemb in menulist)
                  {
                    umpMeta metab = new umpMeta()
                    {
                      title = itemb.aName,
                      i18nKey = itemb.language,
                      icon = itemb.ahtmlIcon,
                      order = itemb.amoduleIndex,
                      keepAlive = false
                    };
                    UsermenuPermissions permissionsb = new UsermenuPermissions()
                    {
                      name = item.aCode+"_"+itemb.aCode,
                      path = itemb.ahtmlUrl,
                      component = itemb.component,
                      meta = metab,
                      children = new List<UsermenuPermissions>()
                    };
                    permissions.children.Add(permissionsb);
                  }
                }

                routes.Add(permissions);
              });
              var home = userLoginResult.list.Where(o => o.aType == 1 && o.status == 1 && o.aCode == "home")?.Select(o=>o.aCode)?.FirstOrDefault();
              userRouteData.home = home;
              userRouteData.routes = routes;
              userLoginResult.list = new List<Menu>();
              LoginCache.GetLoginCache.AddUserRouteData(userLoginResult.token, userRouteData);
              result.count = 1;
            }
            else
            {
              result.code = (int)loginResult;
              if (loginResult == ImplementResult.UserRetrycountError)
              {
                result.msg = loginResult.GetRemark(loginretrytime);
              }
              else if (loginResult == ImplementResult.UserPwdStop)
              {
                result.msg = loginResult.GetRemark(errcount.ToString());
              }
              else if (loginResult == ImplementResult.UserPwd)
              {
                result.msg = loginResult.GetRemark(sycs.ToString() + "|" + errcount.ToString());
              }
              else
              {
                result.msg = loginResult.GetRemark();
              }
            }
            return result;
          },
          null,
          ref result
        );
        return new JsonResult(result);
        execend:
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 根据当前登录账号的菜单权限资源
    /// </summary>
    /// <returns></returns>
    [HttpPost("GetMenuPermission"),AllowAnonymous]
    public async Task<JsonResult> GetMenuPermission()
    {
      CommonResult result = await MenuApplication
        .GetApplication(this.container)
        .GetMenuPermission();
      return new JsonResult(result);
    }

    /// <summary>
    /// 根据用户编号获取对应菜单权限
    /// </summary>
    /// <param name="uId"></param>
    /// <returns></returns>
    [HttpGet("getMenuByUserId")]
    public async Task<JsonResult> getMenuByUserId(int uId)
    {
      CommonResult result = await MenuApplication
        .GetApplication(this.container)
        .getMenuByUserId(uId);
      return new JsonResult(result);
    }

    /// <summary>
    /// 用户退出登录
    /// </summary>
    /// <returns></returns>
    [HttpGet("Logout")]
    public async Task<JsonResult> Logout(string loginToken)
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult();
        var userCode = HttpContextExtendBase.GetLoginCode();
        this.autoface.DoWork(
          BusinessType.user,
          BusinessActionType.loginout,
          "退出系统",
          "用户退出系统",
          BusinessLogType.NoWrite,
          (o) =>
          {
            LoginCache.GetLoginCache.LoginOut(this.mySqlSugar, userCode);
            return result;
          },
          null,
          ref result
        );
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 用户解锁
    /// </summary>
    /// <param name="loginToken"></param>
    /// <param name="pwd"></param>
    /// <returns></returns>
    [HttpGet("GetLockscreen")]
    public async Task<JsonResult> GetLockscreen(string loginToken, string pwd)
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult();
        autoface.DoWork(
          BusinessType.user,
          BusinessActionType.lockscreen,
          BusinessActionType.lockscreen.GetRemark(),
          BusinessActionType.lockscreen.GetRemark(),
          BusinessLogType.writeLogToDataBase,
          (o) =>
          {
            var ispass = LoginCache.GetLoginCache.GetLockscreen(loginToken, pwd);
            if (!ispass)
            {
              result.msg = ImplementResult.PwdError.GetRemark();
            }
            return result;
          },
          null,
          ref result
        );
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 没有找到相关资源
    /// </summary>
    /// <returns></returns>
    [HttpGet("NoPage")]
    public async Task<JsonResult> NoPage()
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult() { data = "没有找到相关资源" };
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 没有权限操作
    /// </summary>
    /// <returns></returns>
    [HttpGet("NoAuthority")]
    public async Task<JsonResult> NoAuthority()
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult()
        {
          msg = ImplementResult.Nopermissiontooperate.GetRemark(),
          code = (int)CodeResult.nolegitimate
        };
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 检查是否有绑定角色资源的权限
    /// </summary>
    /// <returns></returns>
    [HttpGet("CheckAuthority")]
    public async Task<JsonResult> CheckAuthority()
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult();
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 用户登录校验
    /// </summary>
    /// <returns></returns>
    [HttpGet("LoginError")]
    public async Task<JsonResult> LoginError()
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult()
        {
          msg = ImplementResult.UserLoginTimeOut.GetRemark(),
          code = (int)ImplementResult.UserLoginTimeOut
        };
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 创建保存客户端生成的登录验证码
    /// </summary>
    /// <param name="timestamp"></param>
    /// <param name="yzm"></param>
    /// <returns></returns>
    [HttpGet("CreateTimestampYZM"), AllowAnonymous]
    public async Task<JsonResult> CreateTimestampYZM(string timestamp, string yzm)
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult();
        autoface.DoWork(
          BusinessType.user,
          BusinessActionType.verificationcode,
          "登录验证码",
          "创建保存客户端生成的登录验证码",
          BusinessLogType.NoWrite,
          (o) =>
          {
            var yzmdata = LoginCache.GetLoginCache.GetLoginYzm.Where(b => b.Key == timestamp);
            if (yzmdata.Count() > 0)
            {
              LoginCache.GetLoginCache.AddUserLoginYzmSuccess(timestamp, yzm);
            }
            return result;
          },
          null,
          ref result
        );
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 混合验证码
    /// </summary>
    /// <returns></returns>
    [HttpGet("GetUserVerifyCodeb"), AllowAnonymous]
    public FileContentResult MixVerifyCode(string t)
    {
      string code = VerifyCodeUtil
        .GetSingleObj()
        .CreateVerifyCode(VerifyCodeUtil.VerifyCodeType.MixVerifyCode);
      //将验证码记入缓存中
      MemoryUtil.SetMemory(t, code, 5);
      var bitmap = VerifyCodeUtil.GetSingleObj().CreateBitmapByImgVerifyCode(code, 100, 40);
      MemoryStream stream = new MemoryStream();
      bitmap.Save(stream, ImageFormat.Gif);
      return File(stream.ToArray(), "image/gif");
    }

    [HttpGet("GetUserVerifyCode"), AllowAnonymous]
    public FileContentResult Captcha(string t)
    {
      try
      {
        var info = captcha.Generate(t);
        //将验证码记入缓存中
        MemoryUtil.SetMemory(t, info.Code, 5);
        var stream = new MemoryStream(info.Bytes);
        return File(stream.ToArray(), "image/gif");
      }
      catch (Exception ex)
      {
        var ctime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        var msg = ex.Message;
        var sql =
          $"insert into `dd-log`(lmodule,luser,lrole,ltype,lcontent,cTime)values('获取验证码','系统','系统',2,'获取验证码异常:{msg}','{ctime}') ";
        mySqlSugar.ExecuteSql(sql, null, out var msgb);
        return null;
      }
    }

    /// <summary>
    /// 获取用户登录验证码
    /// </summary>
    /// <param name="yzmstr"></param>
    /// <param name="strlength"></param>
    /// <param name="checkNum"></param>
    /// <returns></returns>
    [HttpGet("GetVerificationCode"), AllowAnonymous]
    public async Task<JsonResult> GetVerificationCode(
      string yzmstr,
      int strlength,
      int checkNum = 4
    )
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult();
        var data = LoginManage.CreateRegionCode(strlength, checkNum);
        byte[] buffer = Guid.NewGuid().ToByteArray();
        string timestamp =
          DateTime.Now.ToString("yyyyMMddHHmmssff") + BitConverter.ToInt64(buffer, 0).ToString();
        data.timestamp = timestamp;
        LoginCache.GetLoginCache.AddUserLoginYzm(timestamp, yzmstr);
        LoginCache.GetLoginCache.AddUserLoginYzmSuccess(timestamp, yzmstr);
        data.djyzm = data.djyzm;
        result.data = data;
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 权限判断返回
    /// </summary>
    /// <returns></returns>
    [HttpGet("Fail")]
    public async Task<JsonResult> Fail()
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = HandleBlockedResult.result;
        return new JsonResult(result);
      });
    }

    /// <summary>
    /// 获取省市县信息
    /// </summary>
    /// <returns></returns>
    [HttpGet("GetCity")]
    public async Task<JsonResult> GetCity()
    {
      CommonResult result = await MenuApplication.GetApplication(container).GetCity(mySqlSugar);
      return new JsonResult(result);
    }

    /// <summary>
    /// 白名单禁止访问
    /// </summary>
    /// <returns></returns>
    [HttpGet("WhitesingleLock")]
    public async Task<JsonResult> WhitesingleLock()
    {
      return await Task.Factory.StartNew(() =>
      {
        CommonResult result = new CommonResult()
        {
          msg = ImplementResult.Blacklist.GetRemark(),
          code = (int)CodeResult.blacklist
        };
        return new JsonResult(result);
      });
    }
  }
}
